#include "StdAfx.h"
#include "NeuralNet.h"
#include <time.h>
#include "NeuronTrainerGHA.h"

using namespace std;
NeuralNetwork::NeuralNetwork( unsigned int neuronsQuantity, unsigned int inputsQuantity, unsigned int componentsQuantity )throw(IllegalArgumentException)
{
	if (neuronsQuantity == 0){
		throw IllegalArgumentException("NeturalNetwork class, neuronsQuantity should not be zero");
	}

	if (inputsQuantity == 0){
		throw IllegalArgumentException("NeturalNetwork class, inputsQuantity should not be zero");
	} 

	if (componentsQuantity == 0){
		throw IllegalArgumentException("NeturalNetwork class, componentsQuantity should not be zero");
	} 
	if (neuronsQuantity > componentsQuantity){
		throw IllegalArgumentException("NeturalNetwork class, neuronsQuantity should not be more than componentsQuantity");
	}  

	srand(static_cast<unsigned int>(time(NULL)));
	_learningRate=static_cast<float>((rand()%10+1)/1000.0);
	_inputsQuantity = inputsQuantity;
	_componentsQuantity = componentsQuantity;
	
	_neurons.resize(neuronsQuantity);
	for(unsigned int i=0; i< _neurons.size(); i++){
		_neurons[i] = new Neuron(componentsQuantity);
	}
}


NeuralNetwork::~NeuralNetwork(void)
{
	for (unsigned int i=0; i<_neurons.size();i++){
		delete _neurons[i];
	}
}


vector<vector<float>> NeuralNetwork::calculateWithTrenerGHA(vector<vector<float>> values)throw(IllegalArgumentException)
{
	if (values.size() < _inputsQuantity){
		throw IllegalArgumentException("NeuralNetwork Class: inputs is too less");
	}
	if (values.size() > _inputsQuantity){
		throw IllegalArgumentException("NeuralNetwork Class: inputs is too match");
	}
	if (values[0].size() < _componentsQuantity){
		throw IllegalArgumentException("NeuralNetwork Class: components is too less");
	}
	if (values[0].size() > _componentsQuantity){
		throw IllegalArgumentException("NeuralNetwork Class: components is too match");
	}

	vector<vector <float>> newWeights;
	float oldw=100,diff=100;

	NeuronTrainerGHA hebb(_learningRate);
	int rep=1;
	while(diff>=0.00001){
		for (unsigned int val=0;val<values.size();val++){
			newWeights = hebb.calculateWeights(_neurons, values[val]);
		}
		diff=fabs(oldw-newWeights[newWeights.size()-1][newWeights[0].size()-1]);
		oldw = newWeights[newWeights.size()-1][newWeights[0].size()-1];
		printf("repeat %d\n",rep);
		rep++;
	}
	for (unsigned int j=0;j<_neurons.size();j++){
		_neurons[j]->calculateOutput();
		_neurons[j]->getOutput();
	}
	return newWeights;
}

vector<float> NeuralNetwork::getNeuronOutputs()
{
vector <float> outputs(_neurons.size());
	for (unsigned int j=0;j<_neurons.size();j++){
		outputs[j]=_neurons[j]->getOutput();
	}
	return outputs;
}
